home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.04 Apr 94 / Powering Up / Executing Code / Data -> Resource / DataToRes.c next >
Encoding:
C/C++ Source or Header  |  1994-02-09  |  8.6 KB  |  375 lines  |  [TEXT/MPCC]

  1. // File: DataToRes.c
  2. //
  3. // This is a trivial application which reads a PEF container from the data fork of a file
  4. // and moves that information into a resource in the resource fork of the same file.
  5. //
  6. // Simce this is intended as a tool to help build code resources for SimpleApp, it
  7. // accepts files of type 'DPEF', converts them to 'RPEF', and creates 'RPEF' (128)
  8. // resources.
  9. //
  10. // This same task may be accomplished using MPW Rez.
  11. //
  12.  
  13. #ifndef powerc
  14.     #error This code only runs on a PowerPC machine.
  15. #endif
  16.  
  17. #include <Types.h>
  18. #include <Memory.h>
  19. #include <Resources.h>
  20. #include <Quickdraw.h>
  21. #include <Menus.h>
  22. #include <Events.h>
  23. #include <Windows.h>
  24. #include <Dialogs.h>
  25. #include <AppleEvents.h>
  26. #include <StandardFile.h>
  27. #include <Files.h>
  28. #include <Errors.h>
  29.  
  30. #include <FragLoad.h>
  31.  
  32. // === Useful constants
  33. enum {
  34.         kAppleMenu = 128,
  35.         kFileMenu  = 129,
  36.             kOpenCommand = 1,
  37.             kQuitCommand = 3
  38.     };
  39.  
  40. enum {
  41.         rAboutAlert = 128,
  42.         rErrorAlert = 129
  43.     };
  44.  
  45. enum {
  46.         kPEFData = 'DPEF',
  47.         kPEFResource = 'RPEF'
  48.     };
  49.  
  50. // === Global variables
  51. #if defined(powerc) && !defined(__MWERKS__) // Beginning with DR2, MetroWerks defines "qd" in their runtime
  52.     QDGlobals        qd;
  53. #endif
  54. Boolean            gDone = false;
  55. Boolean            gLaunchedByUser = false;    // True if the user double-clicked on the app
  56.  
  57. // === Function prototypes
  58. void Initialize (void);
  59. void MainLoop (void);
  60. void DoMouseDown (EventRecord theEvent);
  61. void DoMenu (long menuCode);
  62. void FindAndOpenPEF (void);
  63. OSErr ProcessFile (FSSpec fileSpec);
  64. pascal OSErr HandleOAPP (AEDescList *aevt, AEDescList *reply, long refCon);
  65. pascal OSErr HandleODOC (AEDescList *aevt, AEDescList *reply, long refCon);
  66. pascal OSErr HandleQUIT (AEDescList *aevt, AEDescList *reply, long refCon);
  67.  
  68. // === Start of our code
  69. main()
  70. {
  71.     Initialize();
  72.     MainLoop();
  73. }
  74.  
  75.  
  76. // Initialize the ROM managers, set up our menu bar and (only) window, and
  77. // install our Apple event handlers.
  78. void Initialize()
  79. {
  80.     MenuHandle    appleMenu;
  81.     MenuHandle    fileMenu;
  82.     
  83.     // Standard "boilerplate" initialization
  84.     InitGraf(&qd.thePort);
  85.     InitFonts();
  86.     InitWindows();
  87.     InitMenus();
  88.     TEInit();
  89.     InitDialogs(NULL);
  90.     FlushEvents(everyEvent, 0);
  91.  
  92.     // Set up the menu bar
  93.     appleMenu = GetMenu(kAppleMenu);
  94.     if (appleMenu == NULL) {
  95.         // Our resource file is missing! Bail out!
  96.         ExitToShell();
  97.     }
  98.     AddResMenu(appleMenu, 'DRVR');    // Add Desk Accessories
  99.     InsertMenu(appleMenu, 0);
  100.     fileMenu = GetMenu(kFileMenu);
  101.     InsertMenu(fileMenu, 0);
  102.     DrawMenuBar();
  103.     
  104.     // Install our Apple event handlers
  105.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOAPP), 0, false);
  106.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,   NewAEEventHandlerProc(HandleODOC), 0, false);
  107.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,  NewAEEventHandlerProc(HandleQUIT), 0, false);
  108.  
  109.     InitCursor();
  110. }
  111.  
  112.  
  113. // Collect events until the user selects "Quit" (or we get a "Quit" Apple
  114. // event.) If we've loaded some PowerPC code, then give that code a chance
  115. // to execute the event first.
  116. void MainLoop()
  117. {
  118.     EventRecord    theEvent;
  119.     
  120.     while (!gDone) {
  121.         WaitNextEvent(everyEvent, &theEvent, 15L, NULL);        
  122.         switch (theEvent.what) {
  123.             case mouseDown: 
  124.                 DoMouseDown(theEvent);
  125.             break;
  126.  
  127.             case keyDown: {
  128.                 // See if the comamnd key is down. If it is, handle this as
  129.                 // a menu command
  130.                 char    theKey = (theEvent.message & charCodeMask);
  131.  
  132.                 if (theEvent.modifiers & cmdKey)
  133.                     DoMenu(MenuKey(theKey));
  134.             }
  135.             break;
  136.  
  137.             case updateEvt: {
  138.                 WindowPtr    theWindow = (WindowPtr)theEvent.message;
  139.                 
  140.                 BeginUpdate(theWindow);
  141.                 EndUpdate(theWindow);
  142.             }
  143.             break;
  144.                         
  145.             case kHighLevelEvent:
  146.                 AEProcessAppleEvent(&theEvent);
  147.         }
  148.     }
  149. }
  150.  
  151. // Handle mouse clicks either in the menubar or in a window
  152. void DoMouseDown (EventRecord theEvent)
  153. {
  154.     short        part;
  155.     WindowPtr    theWindow;
  156.  
  157.     part = FindWindow(theEvent.where, &theWindow);
  158.     switch (part) {
  159.         case inMenuBar: 
  160.             DoMenu(MenuSelect(theEvent.where));
  161.         break;
  162.  
  163.         case inSysWindow: 
  164.             SystemClick(&theEvent, theWindow);
  165.         break;
  166.  
  167.         case inDrag: {
  168.             Rect dragRect = qd.screenBits.bounds;
  169.             dragRect.top = GetMBarHeight();
  170.             DragWindow(theWindow, theEvent.where, &dragRect);
  171.         }
  172.         break;
  173.     }
  174. }
  175.  
  176.  
  177. // Code to handle the File and Apple menus
  178. void DoMenu (long menuCode)
  179. {
  180.     short    menuID = menuCode >> 16;
  181.     short    itemID = menuCode & 0x0000FFFF;
  182.     
  183.     switch (menuID) {
  184.         case kAppleMenu:
  185.             if (itemID == 1)
  186.                 Alert(128, NULL); // Display the "About" box
  187.         break;
  188.         
  189.         case kFileMenu:
  190.             if (itemID == kOpenCommand) {
  191.                 FindAndOpenPEF();
  192.             }
  193.             else if (itemID == kQuitCommand)
  194.                 gDone = true;
  195.         break;
  196.     }
  197. }
  198.  
  199.  
  200. // Ask the user to locate a bit of code for us, then load
  201. // and execute the code
  202. void FindAndOpenPEF ()
  203. {
  204.     // Open a file of type 'PEF ' or a resource file
  205.     SFTypeList typeList = {kPEFData};
  206.     StandardFileReply     reply;
  207.  
  208.     StandardGetFile(NULL, 3, typeList, &reply);
  209.     if (reply.sfGood)
  210.         ProcessFile(reply.sfFile);
  211. }
  212.  
  213.  
  214. OSErr ReadDataFork (FSSpec fileSpec, Handle *result)
  215. {
  216.     // Get the PEF data stored in the data fork of the file
  217.     OSErr    err;
  218.     long    PEFSize;
  219.     short    refNum;
  220.         
  221.     *result = NULL;
  222.     err = FSpOpenDF(&fileSpec, fsCurPerm, &refNum);
  223.     if (err) goto done;
  224.     err = GetEOF(refNum, &PEFSize);
  225.     if (err) goto done;
  226.     
  227.     // We have the file, and the size, so let's go get the data
  228.     *result = NewHandle(PEFSize);
  229.     err = MemError();
  230.     if (err) goto done;
  231.     
  232.     HLock(*result);
  233.     err = FSRead(refNum, &PEFSize, **result);
  234.     HUnlock(*result);
  235.  
  236. done:
  237.     if (refNum != -1)
  238.         FSClose(refNum);
  239.     return err;
  240. }
  241.  
  242.  
  243. OSErr CreatePEFResource (FSSpec fileSpec, Handle resourceData)
  244. {
  245.     // Create a RPEF resource from the supplied data
  246.     OSErr    err;
  247.     short    refNum;
  248.         
  249.     refNum = FSpOpenResFile(&fileSpec, fsCurPerm);
  250.     err = ResError();
  251.     // See if the resource fork even exists. If not, create one
  252.     if (err == resFNotFound) {
  253.         FSpCreateResFile(&fileSpec, 'SMPA', kPEFData, 0);
  254.         err = ResError();
  255.         if (err == noErr)
  256.             // Try again
  257.             err = CreatePEFResource(fileSpec, resourceData);
  258.         goto done;
  259.     }
  260.     if (err) goto done;
  261.     
  262.     // The file is now open, so create our PEF resource
  263.     AddResource(resourceData, kPEFResource, 128, (StringPtr)"\p");
  264.     WriteResource(resourceData);
  265.     
  266. done:
  267.     if (refNum != -1)
  268.         CloseResFile(refNum);
  269.     return err;
  270. }
  271.  
  272.  
  273. OSErr ConvertToResFile (FSSpec fileSpec)
  274. {
  275.     // Eradicate the data fork and change the file's type
  276.     OSErr    err;
  277.     short    refNum = -1;
  278.     FInfo    finderInfo;
  279.         
  280.     // Change the file's type
  281.     err = FSpGetFInfo(&fileSpec, &finderInfo);
  282.     if (err) goto done;
  283.     finderInfo.fdType = kPEFResource;
  284.     err = FSpSetFInfo(&fileSpec, &finderInfo);
  285.     if (err) goto done;
  286.     
  287.     // Empty the data fork (where the old PEF container lived)
  288.     err = FSpOpenDF(&fileSpec, fsCurPerm, &refNum);
  289.     if (err) goto done;
  290.     err = SetEOF(refNum,0);
  291.     if (refNum != -1)
  292.         CloseResFile(refNum);
  293.     
  294. done:
  295.     return err;
  296. }
  297.  
  298.  
  299. // Load a bit of PowerPC code which is external to this application
  300. OSErr ProcessFile (FSSpec fileSpec)
  301. {
  302.     OSErr    err = noErr;
  303.     short    refNum;
  304.     Handle    PEFData = NULL;
  305.     
  306.     // Stage 1 -- Get the PEF container from the data fork
  307.     err = ReadDataFork(fileSpec, &PEFData);
  308.     if (err) goto done;
  309.     
  310.     // Stage 2 -- Put this into a resource
  311.     err = CreatePEFResource (fileSpec, PEFData);
  312.     DisposeHandle(PEFData); PEFData = NULL;
  313.     if (err) goto done;
  314.     
  315.     // Stage 3 -- Eradicate the data fork and change the file type
  316.     err = ConvertToResFile(fileSpec);
  317.  
  318. done:
  319.     return err;
  320. }
  321.  
  322.  
  323. // Apple event handlers for "Open Application", "Open Document", and
  324. // "Quit"
  325. pascal OSErr HandleOAPP (AEDescList *aevt, AEDescList *reply, long refCon)
  326. {
  327.     gLaunchedByUser = true;
  328.     FindAndOpenPEF();
  329.     return noErr;
  330. }
  331.  
  332.  
  333. pascal OSErr HandleODOC (AEDescList *aevt, AEDescList *reply, long refCon)
  334. // We'll get this if somebody double-clicks on one of our code files
  335. // We'll process any double-clicked or dragged-on files
  336. {
  337.     AEDesc        fileListDesc = {'NULL', NULL};
  338.     long        numFiles, index;
  339.     OSErr        err;
  340.                             
  341.     err = AEGetKeyDesc( aevt, keyDirectObject, typeAEList, &fileListDesc );
  342.     /* Count the list elements */
  343.     err = AECountItems( &fileListDesc, &numFiles);
  344.     if (err) goto done;
  345.                 
  346.     /* now get each file from the list and process it. */
  347.     /* Even though the event contains a list of alises, the Apple Event Manager */
  348.     /* will convert each alias to an FSSpec if we ask it to. */
  349.     for (index = 1; index <= numFiles; index ++) {
  350.         DescType    actualType;
  351.         long        actualSize;
  352.         AEKeyword    actualKeyword;
  353.         FSSpec        theFile;
  354.  
  355.         err = AEGetNthPtr( &fileListDesc, 1, typeFSS, &actualKeyword,
  356.                             &actualType, (Ptr)&theFile, sizeof(theFile), &actualSize);
  357.         if (err == noErr)
  358.             ProcessFile(theFile);
  359.     }
  360.  
  361. done:
  362.     AEDisposeDesc(&fileListDesc);    // no need to check for NULL, as AEDisposeDesc checks first
  363.     // If the user launched us by dragging on some files, then quit
  364.     if (!gLaunchedByUser)
  365.         gDone = true;
  366.     return err;
  367. }
  368.  
  369.  
  370. pascal OSErr HandleQUIT (AEDescList *aevt, AEDescList *reply, long refCon)
  371. {
  372.     gDone = true;
  373.     return noErr;
  374. }
  375.